﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.IsolatedStorage;
using MIDIRemapper.DeviceInterfaces;
using System.Xml.Serialization;

namespace MIDIRemapper.FileInterfaces
{
    partial class FileInterface
    {
        private const string DefaultSaveFileName = "default.xml";

        #region Public Method Shells
        public bool SaveDefaultSettings(DeviceInterface di, SaveOptions so = SaveOptions.Routing_Devices)
        {
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForAssembly();
            bool successful;
            using(IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(
                DefaultSaveFileName, FileMode.Create, FileAccess.Write))
            {
                successful = saveFile(isfs, di, so);
            }
            return successful;
        }

        public bool SaveSettings(string fileUrl, DeviceInterface di, SaveOptions so = SaveOptions.Routing_Devices)
        {
            bool successful;
            using (FileStream fs = new FileStream(fileUrl, FileMode.OpenOrCreate, FileAccess.Write))
            {
                successful = saveFile(fs, di, so);
            }
            return successful;
        }

        public bool LoadDefaultSettings(out string inputDeviceName, out string outputDeviceName,
            out List<Transformable> routes)
        {
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForAssembly();
            bool successful;
            try
            {
                using (IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(
                    DefaultSaveFileName, FileMode.Open, FileAccess.Read))
                {
                    successful = openFile(isfs, out inputDeviceName, out outputDeviceName, out routes);
                }
            }
            catch (Exception e)
            {
                if (e is FileNotFoundException || e is InvalidOperationException)
                {
                    inputDeviceName = null;
                    outputDeviceName = null;
                    routes = null;
                    return false;
                }
                else { throw; }
            }
            return successful;
        }

        public bool LoadSettings(string FileUrl, out string inputDeviceName, out string outputDeviceName,
            out List<Transformable> routes)
        {
            bool successful;

            using (FileStream fs = new FileStream(FileUrl, FileMode.Open, FileAccess.Read))
            {
                successful = openFile(fs, out inputDeviceName, out outputDeviceName, out routes);
            }

            return successful;
        }
        #endregion

        #region Private Read, Save, & Serialization methods
        private bool saveFile(Stream fs, DeviceInterface di, SaveOptions so)
        {
            SaveData data = new SaveData();
            if (so.SaveRouting())
            {
                data.routes = di.GetTransformations();
            }
            if (so.SaveDevices())
            {
                data.inputDeviceName = di.inputDeviceName;
                data.outputDeviceName = di.outputDeviceName;
            }

            XmlSerializer xs = new XmlSerializer(typeof(SaveData));
            xs.Serialize(fs, data);
            fs.Flush();

            return true;
        }

        private bool openFile(Stream fs, out string inputDeviceName, out string outputDeviceName,
            out List<Transformable> routes)
        {
            SaveData data = new SaveData();
            XmlSerializer xs = new XmlSerializer(typeof(SaveData));

            fs.Position = 0;
            data = (SaveData)xs.Deserialize(fs);

            inputDeviceName = data.inputDeviceName;
            outputDeviceName = data.outputDeviceName;
            routes = data.routes;
            return true;
        }
        #endregion
    }
}
